<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2020-02-21
 * Time: 16:40
 */

namespace Zwwl2016\Cluster;

//refer to https://www.cnblogs.com/archermeng/p/7537431.html
 class ClusterCronTaskParameterPair
{
    private $second;
    private $minute;
    private $hour;
    private $dayOfMonth;
    private $month;
    private $dayOfWeek;
    private $year="";

     private $cron;
     private $clusterParameters;

     /**
      * @return ClusterCronTaskParameterPair
      */
     public static function Instance()
     {
        return new ClusterCronTaskParameterPair();
     }

     public function getCronString()
     {
         return $this->cron;
     }

     /**
      * @param ClusterParameters $clusterParameters
      * @return ClusterCronTaskParameterPair
      */
     public function setClusterParameters(ClusterParameters $clusterParameters)
     {
         $this->clusterParameters=$clusterParameters;
         return $this;
     }

     /**
      * @return array
      */
     public function getParametersArray()
     {
         $arr=$this->clusterParameters->getArray();
         return $arr;
     }

     /**
      * @param $val
      * @return ClusterCronTaskParameterPair
      */
     public function setSecond($val)
     {
         $this->second=$val;
         return $this;
     }

     /**
      * @param $val
      * @return ClusterCronTaskParameterPair
      */
     public function setMinute($val)
     {
         $this->minute=$val;
         return $this;
     }

     /**
      * @param $val
      * @return ClusterCronTaskParameterPair
      */
     public function setHour($val)
     {
         $this->hour=$val;
         return $this;
     }

     /**
      * @param $val
      * @return ClusterCronTaskParameterPair
      */
     public function setDayOfMonth($val)
     {
         $this->dayOfMonth=$val;
         return $this;
     }

     /**
      * @param $val
      * @return ClusterCronTaskParameterPair
      */
     public function setMonth($val)
     {
         $this->month=$val;
         return $this;
     }

     /**
      * @param $val
      * @return ClusterCronTaskParameterPair
      */
     public function setDayOfWeek($val)
     {
         $this->dayOfWeek=$val;
         return $this;
     }

     /**
      * @param $val
      * @return ClusterCronTaskParameterPair
      */
     public function setYear($val)
     {
         $this->year=$val;
         return $this;
     }

     /**
      * @param $cronString
      * @return ClusterCronTaskParameterPair
      * @throws \Exception
      */
     public function setCronString($cronString)
     {
         $arr = explode(" ",$cronString);
         $count=count($arr);
         if($count!=6&&$count!=7)
         {
             throw new \Exception("cron format not valid length!:"+$cronString);
         }
         if(
             !self::checkNotHasUndefinedSymbol($arr[0],"0123456789,-*/")
             ||!self::checkNotHasUndefinedSymbol($arr[1],"0123456789,-*/")
             ||!self::checkNotHasUndefinedSymbol($arr[2],"0123456789,-*/")
             ||!self::checkNotHasUndefinedSymbol($arr[3],"0123456789,-*/?LWC")
             ||!self::checkNotHasUndefinedSymbol($arr[4],"0123456789,-*/")
             ||!self::checkNotHasUndefinedSymbol($arr[5],"0123456789,-*/?LC#")
             ||($count==7&&!self::checkNotHasUndefinedSymbol($arr[6],"0123456789,-*/"))
         )
         {
             throw new \Exception("cron has not valid symbo!:"+$cronString);
         }
         if(
             !self::checkDigitValue($arr[0],0,59)
             ||!self::checkDigitValue($arr[1],0,59)
             ||!self::checkDigitValue($arr[2],0,23)
             ||!self::checkDigitValue($arr[3],1,31)
             ||!self::checkDigitValue($arr[4],1,12)
             ||!self::checkDigitValue($arr[5],1,7)
             ||(count($arr)==7&&!self::checkDigitValue($arr[6],1970,2099))
         )
         {
             throw new \Exception("cron has not valid value!:"+$cronString);
         }
         if(!self::checkMonthString($arr[4]))
         {
             throw new \Exception("cron has not valid month!:"+$cronString);
         }
         if(!self::checkWeekDayString($arr[5]))
         {
             throw new \Exception("cron has not valid weekday!:"+$cronString);
         }
         $this->second=$arr[0];
         $this->minute=$arr[1];
         $this->hour=$arr[2];
         $this->dayOfMonth=$arr[3];
         $this->month=$arr[4];
         $this->dayOfWeek=$arr[5];
         if($count==7)
         {
             $this->year=$arr[6];
         }
         $this->cron=$cronString;
         return $this;
     }


    private function checkDigitValue($val,$min,$max)
    {
        preg_match_all("/[0-9]+/" ,$val,$out,PREG_PATTERN_ORDER);
        if(empty($out[0])) {
            return true;
        }
        foreach($out[0] as $number)
        {
            if($val<$min||$val>$max)
            {
                return false;
            }
        }
        return true;
    }

    private function checkMonthString($val)
    {
        preg_match_all("/[A-Z]+/" ,$val,$out,PREG_PATTERN_ORDER);
        if(empty($out[0])) {
            return true;
        }
        $arr=["JAN",
            "FEB",
            "MAR",
            "APR",
            "MAY",
            "JUN",
            "JUL",
            "AUG",
            "SEP",
            "OCT",
            "NOV",
            "DEC"];
        foreach($out[0] as $str)
        {
            if(!in_array($val,$arr))
            {
                return false;
            }
        }
        return false;
    }

    private function checkWeekDayString($val)
    {
        preg_match_all("/[A-Z]+/" ,$val,$out,PREG_PATTERN_ORDER);
        if(empty($out[0])) {
            return true;
        }
        $arr=["MON","THU","WED","THU","FRI","SAT","SUN"];
        foreach($out[0] as $str)
        {
            if(!in_array($val,$arr))
            {
                return false;
            }
        }
        return false;
    }

    private function checkNotHasUndefinedSymbol($val,$definedSymbolString)
    {
        $arr = preg_split("//u", $definedSymbolString, -1, PREG_SPLIT_NO_EMPTY);
        $val=str_replace($arr,"",$val);
        if(strlen($val)>0)
        {
            return false;
        }
        return true;
    }
}